package com.yuhang.demo.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yuhang.demo.ExcelListener.UserExcelListener;
import com.yuhang.demo.common.MD5;
import com.yuhang.demo.common.Result;
import com.yuhang.demo.dao.RoleDao;
import com.yuhang.demo.dao.UserExtendDao;
import com.yuhang.demo.entity.*;
import com.yuhang.demo.entity.excel.UserData;
import com.yuhang.demo.exceptionHandler.MyException;
import com.yuhang.demo.service.UserExtendService;
import com.yuhang.demo.service.UserRoleXrefService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.yuhang.demo.dao.UserDao;
import com.yuhang.demo.service.UserService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {


    @Autowired
    private UserExtendService userExtendService;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private UserExtendDao userExtendDao;

    @Autowired
    private UserRoleXrefService userRoleXrefService;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Value("${app.roleName}")
    private String defaultRoleName;


    public volatile Boolean out;

    @Override
    public boolean repeatPhone(String phone) {

        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();

        wrapper.eq("phone",phone);
        Integer count = baseMapper.selectCount(wrapper);

        if(count > 0) {
            return true;
        }

        return false;

    }

    @Override
    public UserEntity login(UserEntity member) {

        //获取登录手机号和密码
        String mobile = member.getPhone();
        String password = member.getPassword();

        //手机号和密码非空判断
        if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)) {
            throw new MyException(20001,"登录失败");
        }

        //判断手机号是否正确
//        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
//        wrapper.eq("phone",mobile);
//        UserEntity entity = baseMapper.selectOne(wrapper);

        UserEntity entity = baseMapper.selectOne(mobile);
        //判断查询对象是否为空
        if(entity == null) {//没有这个手机号
            throw new MyException(20001,"登录失败");
        }

        //判断密码
        //因为存储到数据库密码肯定加密的
        //把输入的密码进行加密，再和数据库密码进行比较
        //加密方式 MD5
        if(entity.getPassword().equals(MD5.encrypt(password))) {
            throw new MyException(20001,"登录失败");
        }

        //判断用户是否禁用
        if(entity.getEnableStatus() != 1) {
            throw new MyException(20001,"登录失败");
        }

        //登录成功
        return entity;
    }

    @Override
    public Boolean isPhoneNumber(String phone) {
        if (StringUtils.isEmpty(phone)) {
            return false;
        }
        if (phone.length() != 11) {
            return false;
        }
//        Pattern pattern = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$");
//        Matcher matcher = pattern.matcher(phone);
//
//        if (matcher.matches()) {
//            return true;
//        }
//        return false;
        String regExp = "^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])|(166)|(17[3,5,6,7,8])" +
            "|(18[0-9])|(19[8,9]))\\d{8}$";
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(phone);
        return m.matches();
    }

    @Override
    public void saveUser(UserEntity user, UserExtendEntity userExtendEntity) {

        baseMapper.saveUser(user);

        userExtendEntity.setUserId(user.getId());

        userExtendService.save(userExtendEntity);

    }

    @Override
    public void saveUser(UserEntity user) {

        baseMapper.saveUser(user);

        System.out.println(user.getId());

//        userExtendEntity.setUserId(user.getId());

//        userExtendService.save(userExtendEntity);

    }

    @Override
    public Boolean saveUserList(MultipartFile file, UserService userService) {

        try {
            Future<Boolean> submit = threadPoolExecutor.submit(new Callable<Boolean>() {
                //文件输入流
                InputStream in = null;
                @Override
                public Boolean call() throws Exception {
                    try {
                        //标志任务运行中
                        out = false;

                        in = file.getInputStream();
                        //调用方法进行读取
                        EasyExcel.read(in, UserData.class,new UserExcelListener(userService)).sheet().doRead();

                        //睡上10s
                        TimeUnit.SECONDS.sleep(10);

                    } catch (IOException e) {
                        e.printStackTrace();
                        return out;
                    }
                    out = true;
                    return out;
                }
            });

            return submit.get();

//            boolean done = submit.isDone();

        }catch (Exception e){
            e.printStackTrace();
            return false;
        }finally {
            threadPoolExecutor.shutdown();
        }
    }

    @Override
    public Boolean create(TotalEntity totalEntity) {

        try {
            UserEntity userEntity = totalEntity;

            //加密
            userEntity.setPassword(MD5.encrypt(userEntity.getPassword()));

            //判断手机号
            Boolean number = isPhoneNumber(userEntity.getPhone());

            //判断手机号是否重复
            boolean isRepeat = repeatPhone(userEntity.getPhone());

            if (number && !isRepeat) {

                baseMapper.saveUser(userEntity);
                Integer id = userEntity.getId();

                RoleEntity role = totalEntity.getRoleEntity();

                //如果用户不创建角色，就使用默认角色
                if (StringUtils.isEmpty(role)) {
                    role.setRoleName(defaultRoleName);
                }

                roleDao.saveRole(role);
                Integer roleId = totalEntity.getRoleEntity().getId();

                //如果用户填写了扩展信息
                if (!StringUtils.isEmpty(totalEntity.getExtendEntity())) {
                    totalEntity.getExtendEntity().setUserId(id);
                    userExtendService.save(totalEntity.getExtendEntity());
                }

                //维护角色与用户的信息
                UserRoleXrefEntity xrefEntity = new UserRoleXrefEntity();

                xrefEntity.setRoleId(roleId);
                xrefEntity.setUserId(id);

                userRoleXrefService.save(xrefEntity);

                return true;

            }
        } catch (Exception e) {
            //手动回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();
            throw new MyException(20001,"创建用户异常");
        }

        return false;

    }

    @Override
    public Integer updateUser(TotalEntity totalEntity) {

        try {

            UserExtendEntity extendEntity = totalEntity.getExtendEntity();
            Integer userId = totalEntity.getId();

            return userExtendDao.saveUserExtend(extendEntity, userId);
        } catch (Exception e) {

            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();

            throw new MyException(20001,"修改异常");
        }


    }

    @Override
    public Boolean deleteUser(Integer userId) {

        int i = this.baseMapper.deleteUser(userId);
        if (i > 0) {
            return true;
        }
        return false;
    }

    @Override
    public Boolean getOutValue() {
        return out;
    }


}